﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;

// Written by Will and Ying

namespace VRP_GTS
{
    class ProgramEntry
    {
        // a method can deep copy any types of serializable objects
        public static T DeepCopy<T>(T obj)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, obj);
                stream.Position = 0;

                return (T)formatter.Deserialize(stream);
            }
        }

        static void Main(string[] args)
        {
            Stopwatch timer = new Stopwatch();                                                      // get running time
            timer.Start();                                                                          // start to calculate time               

            string inputFile;

            // If there are command line arguments, the first one is the file name
            if (args.Length != 0)
                inputFile = args[0];
            else
                inputFile = "Golden_01.vrp";

            // Create the parser object, and read in all the data from file. This object can read ANY TSPLIB file. Code borrowed from HeuristicLab.
            TSPLIBParser myParser = new TSPLIBParser(inputFile);
            myParser.Parse();

            // Create the vrp data object, using the parsed data
            CVRPData vrpData = new CVRPData(myParser);

            // Run the savings method heuristics
            CVRPSolution currentBestSolution = Heuristics.SavingsMethod(vrpData);
            // Store the node list associated with the currentBestSolution
            // Must make sure that the nodes in node list are consistent with nodes in currentBestSolution
            // by consistent I mean the nodes must be the same object
            List<Node> currentBestNodeList = vrpData.NodeList;
          
            // TODO: if you comment out the randomized savings code, the GTS works fine - with the solution from the original savings method
            // If it is not commented, as is right now, GTS gives an error

            //Console.WriteLine("Starting randomized heuristic");
            int k = 0;
            while (timer.Elapsed.TotalMinutes < 0.1)
            //while (k < 1)
            {
                //initSolution = Heuristics.SavingsMethod(vrpData);
                CVRPSolution tempSolution = Heuristics.RandomizedSavingsMethod(vrpData);
                if (tempSolution.TotalCost < currentBestSolution.TotalCost)
                {
                    //currentBestSolution = ProgramEntry.DeepCopy<CVRPSolution>(tempSolution);
                    // Should not use DeepCopy, otherwise the nodes in vrpData.NodeList are not the same as in the currentBestSolution
                    currentBestSolution = tempSolution;
                    currentBestNodeList = vrpData.NodeList;   // Update the currentBestNodeList as well
                    Console.WriteLine("Randomized better cost found.\nTotalcost :  " + currentBestSolution.TotalCost);
                    currentBestSolution.CheckFeasibility(vrpData);
                }
                k++;
            }


            Console.WriteLine("After randomized cost" + currentBestSolution.TotalCost);
            //initSolution.CheckFeasibility(vrpData);

            double initTotalCost = currentBestSolution.TotalCost;
            int initNumOfVehicles = currentBestSolution.TourList.Count;
            
            // Run the GTS heuristics
            // Before passing the vrpData and currentBestSolution into GTS method
            // Make sure that the NodeList and LinkMatrix are consistent with the currentBestSolution
            vrpData.NodeList = currentBestNodeList;
            vrpData.CreateLinkMatrix();
            CVRPSolution mySolution = Heuristics.GTS(vrpData, currentBestSolution);

            timer.Stop();                                                                   // stop to calculate run time
            TimeSpan totalTime = timer.Elapsed;                                             // get the elapsed time as a TimeSpan value

            // Check if the solution is feasible
            mySolution.CheckFeasibility(vrpData);

            // Output the solution
            //mySolution.WriteToFile(inputFile + ".opt", totalTime);

            // report in a csv file 
            ////It is comma delimented, so if opening in a spreadsheet can seperate to different columns by commas
            string teamName = "Will&Ying";
            string filepath = "Will&Ying.csv";
            using (StreamWriter writer = new StreamWriter(filepath, true))
            {
                writer.WriteLine(teamName + "," + inputFile + "," + initTotalCost + "," + initNumOfVehicles + "," + mySolution.TotalCost + "," + mySolution.TourList.Count);
            }
            
            Console.ReadKey();
        }

    }
}
